﻿using Modbus.Device;
using System.Net.Sockets;

namespace 凯蒽斯.Help
{
    public class ModbusHelp : IDisposable
    {
        public event Action<string> Message;
        private readonly TcpClient _tcpClient;
        private readonly string _ipAddress;
        private readonly int _port;
        private ModbusIpMaster _master;

        public ModbusHelp(string ipAddress, int port = 502)
        {
            Message += MainWindow.messageInvoke;
            _ipAddress = ipAddress;
            _port = port;
            _tcpClient = new TcpClient();
        }

        /// <summary>
        /// 连接 Modbus TCP 设备
        /// </summary>
        public async Task ConnectAsync()
        {
            if (_tcpClient.Connected) return;

            try
            {
                await _tcpClient.ConnectAsync(_ipAddress, _port).ConfigureAwait(false);

                // 适配NModbus版本：通过TcpClient创建Modbus主站
                _master = ModbusIpMaster.CreateIp(_tcpClient);

                
            }
            catch (SocketException ex)
            {
                Message.Invoke($"连接失败：{ex.Message}");
            }
        }

        /// <summary>
        /// 异步读取线圈（功能码 0x01）
        /// <param name="unitId">从站</param>
        /// <param name="startAddress">起始地址</param>
        /// <param name="count">数量</param>
        /// <returns></returns>

        public async Task<bool[]> ReadCoilsAsync(byte unitId, ushort startAddress, ushort count)
        {
            ValidateConnection();
            // NModbus同步方法包装为异步（部分版本无原生Async方法）
            return await Task.Run(() =>
                _master.ReadCoils(unitId, startAddress, count)
            ).ConfigureAwait(false);
        }
        /// <summary>
        /// 读取离散输入状态（功能码 0x02）
        /// <param name="unitId">从站</param>
        /// <param name="startAddress">起始地址</param>
        /// <param name="count">数量</param>
        /// <returns></returns>
        public async Task<bool[]> ReadInputsAsync(byte unitId, ushort startAddress, ushort count)
        {
            ValidateConnection();
            // NModbus同步方法包装为异步（部分版本无原生Async方法）
            return await Task.Run(() =>
                _master.ReadInputs(unitId, startAddress, count)
            ).ConfigureAwait(false);
        }
        /// <summary>
        /// 异步读取保持寄存器（功能码 0x03）
        /// <param name="unitId">从站</param>
        /// <param name="startAddress">起始地址</param>
        /// <param name="count">数量</param>
        /// <returns></returns>
        public async Task<ushort[]> ReadHoldingRegistersAsync(byte unitId, ushort startAddress, ushort count)
        {
            if (startAddress == 2000&&count==1000)
            {
                int a = 0;
            }
            ValidateConnection();
            var allRegisters = new List<ushort>();
            ushort remainingCount = count;
            ushort currentStartAddress = startAddress;
            // 2. 分批次读取（每次最多125个，符合Modbus协议）
            while (remainingCount > 0)
            {
                ushort batchCount = (ushort)Math.Min(remainingCount, (ushort)125); // 单次最大125

                try
                {
                    // 同步方法包装为异步（保持原有逻辑）
                    ushort[] batchRegisters = await Task.Run(() =>
                    {
                        ValidateConnection(); // 检查连接状态
                        return _master.ReadHoldingRegisters(unitId, currentStartAddress, batchCount);
                    }).ConfigureAwait(false);

                    allRegisters.AddRange(batchRegisters);
                }
                catch (Exception ex)
                {
                    // 包装其他异常（如连接失败、超时等）
                    Message.Invoke(
                        $"读取失败：从站={unitId}，起始地址={currentStartAddress}，本次读取数量={batchCount}"
                    );
                }

                // 3. 更新下一批次参数
                remainingCount -= batchCount;
                currentStartAddress += batchCount;
            }

            return allRegisters.ToArray();
        }
        /// <summary>
        /// 异步读取输入寄存器（功能码 0x04）
        /// <param name="unitId">从站</param>
        /// <param name="startAddress">起始地址</param>
        /// <param name="count">数量</param>
        /// </summary>
        public async Task<ushort[]> ReadInputRegistersAsync(byte unitId, ushort startAddress, ushort count)
        {
            ValidateConnection();
            // 同步方法包装为异步
            return await Task.Run(() =>
                _master.ReadInputRegisters(unitId, startAddress, count)
            ).ConfigureAwait(false);
        }
        /// <summary>
        /// 异步写单线圈（功能码 0x05）
        /// <param name="unitId">从站</param>
        /// <param name="startAddress">线圈地址</param>
        /// <param name="value"></param>
        /// <returns></returns>
        public async Task WriteSingleCoilsAsync(byte unitId, ushort startAddress, bool value)
        {
            ValidateConnection();
            // NModbus同步方法包装为异步（部分版本无原生Async方法）
            await Task.Run(() =>
                _master.WriteSingleCoil(unitId, startAddress, value)
            ).ConfigureAwait(false);
        }
       
        /// 异步写单保存寄存器（功能码 0x06）
        /// 
        /// <param name="unitId">从站地址</param>
        /// <param name="registerAddress">寄存器地址</param>
        /// <param name="value">值</param>
        /// <returns></returns>
        public async Task WriteSingleRegisterAsync(byte unitId, ushort registerAddress, ushort value)
        {
            ValidateConnection();
            // NModbus同步方法包装为异步（部分版本无原生Async方法）
            await Task.Run(() =>
                _master.WriteSingleRegister(unitId, registerAddress, value)
            ).ConfigureAwait(false);
        }
        /// <summary>
        /// 异步写多线圈（功能码 0x15）
        /// </summary>
        /// <param name="unitId">从站地址</param>
        /// <param name="startAddress">线圈地址</param>
        /// <param name="count">值</param>
        /// <returns></returns>
        public async Task WriteMultipleCoilsAsync(byte unitId, ushort startAddress, bool[] count)
        {
            ValidateConnection();
            // 同步方法包装为异步
            await Task.Run(() =>
                _master.WriteMultipleCoils(unitId, startAddress, count)
            ).ConfigureAwait(false);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="unitId">从站地址</param>
        /// <param name="startAddress">线圈地址param>
        /// <param name="values">值</param>
        /// <returns></returns>
        public async Task WriteMultipleRegistersAsync(byte unitId, ushort startAddress, ushort[] values)
        {
            ValidateConnection();
            // 同步方法包装为异步
            await Task.Run(() =>
                _master.WriteMultipleRegistersAsync(unitId, startAddress, values)
            ).ConfigureAwait(false);
        }
        /// <summary>
        /// 异步读取输入寄存器（功能码 0x16）
        /// </summary>
        /// <param name="unitId">从站地址</param>
        /// <param name="startAddress">寄存器地址</param>
        /// <param name="value">值</param>
        /// <returns></returns>
        public async Task ReadInputRegistersAsync(byte unitId, ushort startAddress, ushort[] value)
        {
            ValidateConnection();
            // 同步方法包装为异步
            await Task.Run(() =>
                _master.WriteMultipleRegisters(unitId, startAddress, value)
            ).ConfigureAwait(false);
        }


        private void ValidateConnection()
        {
            if (!_tcpClient.Connected || _master == null)
            {
                throw new InvalidOperationException("未连接到设备，请先调用 ConnectAsync");
            }
        }

        public void Disconnect()
        {
            if (_tcpClient.Connected)
            {
                _tcpClient.Close();
            }
        }

        public void Dispose()
        {
            Disconnect();
            _tcpClient.Dispose();
        }

        
    }
}